#include "map_view_model.h"
#include "application/map/map_application_service.h" // Only include application layer
#include <QDebug>

namespace presentation {

// Default constructor for QML instantiation
MapViewModel::MapViewModel(QObject* parent)
    : BaseViewModel(parent)
    , mapAppService_(nullptr)
    , mapName_("Demo Map")
    , mapBounds_(QRectF(0, 0, 800, 600))
    , mapResolution_(0.05)
    , isMapLoaded_(false)
    , currentPosition_(QPointF(400, 300))
    , currentAngle_(0.0)
{
    // Initialize with demo data for testing
    qDebug() << "MapViewModel created in demo mode (no service)";

    // Create some demo map data
    kernel::MapDisplayDto demoData;
    demoData.mapName = "Demo Map";
    demoData.bounds = QRectF(0, 0, 800, 600);
    demoData.resolution = 0.05;

    // Add some demo stations
    demoData.stations.append(kernel::StationDisplayInfo(QPointF(100, 100), "Station_A", "LocationMark", "Normal"));
    demoData.stations.append(kernel::StationDisplayInfo(QPointF(300, 200), "Station_B", "LocationMark", "Charge"));
    demoData.stations.append(kernel::StationDisplayInfo(QPointF(500, 300), "Station_C", "LocationMark", "Normal"));
    demoData.stations.append(kernel::StationDisplayInfo(QPointF(700, 400), "Station_D", "LocationMark", "Park"));

    // Add some demo paths
    kernel::PathDisplayInfo path1;
    path1.points = {QPointF(100, 100), QPointF(200, 150), QPointF(300, 200)};
    path1.pathType = "bezier";
    path1.name = "Path_A_B";
    demoData.paths.append(path1);

    kernel::PathDisplayInfo path2;
    path2.points = {QPointF(300, 200), QPointF(400, 250), QPointF(500, 300)};
    path2.pathType = "bezier";
    path2.name = "Path_B_C";
    demoData.paths.append(path2);

    // Sync legacy fields for compatibility
    demoData.syncLegacyFields();

    mapDisplayData_ = demoData;
    
    // 延迟初始化，确保QML绑定完成
    delayedInitialize();
}

MapViewModel::MapViewModel(application::MapApplicationService* mapAppService, QObject* parent)
    : BaseViewModel(parent)
    , mapAppService_(mapAppService)
{
    if (!mapAppService_) {
        qWarning() << "MapViewModel: MapApplicationService is null!";
        return;
    }

    // Connect to application service signals
    connect(mapAppService_, &application::MapApplicationService::mapLoadFinished,
            this, &MapViewModel::onMapLoadFinished);
    connect(mapAppService_, &application::MapApplicationService::mapLoadFailed,
            this, &MapViewModel::onMapLoadFailed);
    connect(mapAppService_, &application::MapApplicationService::currentPositionChanged,
            this, &MapViewModel::onCurrentPositionChanged);

    // Initialize cached properties if map is already loaded
    if (mapAppService_->isMapLoaded()) {
        updateCachedProperties();
    }
    
    // 延迟初始化，确保QML绑定完成
    delayedInitialize();
}

bool MapViewModel::loadMap(const QString& mapName) {
    if (!mapAppService_) {
        // Demo mode - emit error and suggest proper service injection
        qWarning() << "MapViewModel: No application service injected. Cannot load real map files.";
        qDebug() << "MapViewModel: Please inject MapApplicationService for proper map loading.";
        emit mapLoadFailed("需要注入 MapApplicationService 以加载真实地图文件");
        return false;
    }

    auto result = mapAppService_->loadMapFromFile(mapName);
    return result.isSuccess();
}

void MapViewModel::refreshMapData() {
    if (mapAppService_) {
        mapAppService_->refreshMapData();
        updateCachedProperties();
    }
}

bool MapViewModel::switchToFloor(int floor) {
    if (!mapAppService_) {
        qWarning() << "MapViewModel: No application service injected. Cannot switch floor.";
        return false;
    }

    auto result = mapAppService_->switchToFloor(floor);
    if (result.isSuccess()) {
        updateCachedProperties();
        emit currentFloorChanged();
        emit mapChanged();
        return true;
    } else {
        qWarning() << "MapViewModel: Failed to switch to floor" << floor << ":" << result.getErrorMessage();
        return false;
    }
}

QVector<QString> MapViewModel::getStationNames() const {
    if (!mapAppService_) {
        return QVector<QString>();
    }
    int floor = mapAppService_->getCurrentFloor();
    if (floor < 0) {
        return QVector<QString>();
    }
    return mapAppService_->getAllStationNames(floor);
}

QPointF MapViewModel::getStationPosition(const QString& stationName) const {
    if (!mapAppService_) {
        return QPointF();
    }
    int floor = mapAppService_->getCurrentFloor();
    if (floor < 0) {
        return QPointF();
    }
    auto position = mapAppService_->getStationPosition(stationName, floor);
    return QPointF(position.x, position.y);
}

int MapViewModel::getFloorForMap(const QString& mapName) const {
    if (!mapAppService_ || mapName.isEmpty()) {
        return -1;
    }
    return mapAppService_->getFloorForMapName(mapName);
}


void MapViewModel::onMapLoadFinished() {
    updateCachedProperties();
    qDebug() << "MapViewModel: map load finished. Floors:" << loadedFloors_;
    emit mapLoadedChanged();
    emit mapChanged();
}

void MapViewModel::onMapLoadFailed(const QString& error) {
    isMapLoaded_ = false;
    mapName_.clear();
    mapBounds_ = QRectF();
    mapResolution_ = 1.0;
    mapDisplayData_.clear();

    emit mapLoadedChanged();
    emit mapChanged();
    emit mapLoadFailed(error);
}

void MapViewModel::onCurrentPositionChanged() {
    if (!mapAppService_) {
        return;
    }

    auto pos = mapAppService_->getCurrentPosition();
    currentPosition_ = QPointF(pos.x, pos.y);
    currentAngle_ = mapAppService_->getCurrentAngle();

    emit currentPositionChanged();
}

void MapViewModel::updateCachedProperties() {
    if (!mapAppService_) {
        return;
    }

    const auto floors = mapAppService_->getLoadedFloors();
    if (loadedFloors_ != floors) {
        loadedFloors_ = floors;
        emit loadedFloorsChanged();
    }

    if (!mapAppService_->isMapLoaded()) {
        return;
    }

    mapName_ = mapAppService_->getCurrentMapName();
    mapResolution_ = mapAppService_->getMapResolution();
    isMapLoaded_ = mapAppService_->isMapLoaded();
    currentFloor_ = mapAppService_->getCurrentFloor();

    auto bounds = mapAppService_->getMapBounds();
    mapBounds_ = QRectF(0, 0, bounds.x, bounds.y);

    auto pos = mapAppService_->getCurrentPosition();
    currentPosition_ = QPointF(pos.x, pos.y);
    currentAngle_ = mapAppService_->getCurrentAngle();

    mapDisplayData_ = mapAppService_->getMapForDisplay();
}

void MapViewModel::initialize()
{
    if (isInitialized()) {
        return;
    }

    qDebug() << "MapViewModel: Initializing with service" << (mapAppService_ ? "injected" : "demo mode");

    try {
        // 如果有服务，进行服务相关的初始化
        if (mapAppService_) {
            // 自动加载默认地图
            auto result = mapAppService_->loadDefaultMap();
            if (result.isSuccess()) {
                qDebug() << "MapViewModel: Default map loading initiated";
            } else {
                qDebug() << "MapViewModel: No default map available:" << result.getErrorMessage();
            }
            qDebug() << "MapViewModel: Service-based initialization completed";
        } else {
            qDebug() << "MapViewModel: Demo mode initialization completed";
        }

        // 调用基类初始化
        BaseViewModel::initialize();

    } catch (const std::exception& e) {
        handleError(QString("MapViewModel initialization failed: %1").arg(e.what()));
    }
}

void MapViewModel::cleanup()
{
    if (!isInitialized()) {
        return;
    }

    qDebug() << "MapViewModel: Cleaning up";
    
    try {
        // 清理地图相关资源
        if (mapAppService_) {
            // 断开信号连接
            disconnect(mapAppService_, nullptr, this, nullptr);
            qDebug() << "MapViewModel: Disconnected from MapApplicationService";
        }
        
        // 清理缓存数据
        mapName_.clear();
        mapBounds_ = QRectF();
        mapResolution_ = 1.0;
        isMapLoaded_ = false;
        currentPosition_ = QPointF();
        currentAngle_ = 0.0;
        mapDisplayData_.clear();
        
        // 调用基类清理
        BaseViewModel::cleanup();
        
        qDebug() << "MapViewModel: Cleanup completed";
        
    } catch (const std::exception& e) {
        qWarning() << "MapViewModel: Exception during cleanup:" << e.what();
    }
}

} // namespace presentation
